﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using S9PalCommon;
using S9PalCommon.ArtistLibrary;

namespace LastFMPhotoCrawler
{
    public class ArtistPhotoSyncer2 : Syncer
    {
        private const String c_oldFileMarker = "old";
        private const String c_relativeSyncPath = "System\\Flash UI\\Library";
        private Library artistLibrary;

        public ArtistPhotoSyncer2()
        {
            this.artistLibrary = S9PalCommon.Global.ArtistLibrary;
            this.Name = "Artist Photo Syncer";
        }

        protected override void OnStart()
        {
            SortedList<String, Artist> artists = artistLibrary.Artists;

            for (int i = 0; i < artists.Count; i++)
            {
                List<ArtistPhoto> photos = artists.ElementAt(i).Value.Photos;
                String artistName = artists.ElementAt(i).Value.Name;

                ManageExistingPhotos(photos, artistName);
                AddNewPhotos(photos, artistName);
                
                S9PalCommon.Global.ArtistLibrary.SaveLibrary();
            }
        }

        // Copy new photos over to the device.
        private void AddNewPhotos(List<ArtistPhoto> photos, String artistName)
        {
            for (int i = 0; i < photos.Count; i++)
            {
                if (photos[i].SyncPhoto && photos[i].DeviceFileName == null)
                {
                    String purgedArtistName = Helper.RemoveInvalidFileNameCharacters(artistName);
                    String sourcePath = artistLibrary.LibraryDirectory + "\\" + purgedArtistName + "\\" + photos[i].LocalFileName;
                    String destPath = Drive + c_relativeSyncPath + "\\" + purgedArtistName + "\\" + (i + 1).ToString() + ".jpg";

                    if (!File.Exists(destPath))
                    {
                        bool retry = false;

                        do
                        {
                            try
                            {
                                File.Copy(sourcePath, destPath);
                                photos[i].DeviceFileName = Path.GetFileName(destPath);
                                retry = false;
                            }
                            catch (DirectoryNotFoundException)
                            {
                                Directory.CreateDirectory(Path.GetDirectoryName(destPath));
                                retry = true;
                            }
                        } while (retry);
                    }
                }
            }
        }

        // Perform any necessary renames and deletes on files already on the device.
        private void ManageExistingPhotos(List<ArtistPhoto> photos, String artistName)
        {
            for (int i = 0; i < photos.Count; i++)
            {
                String purgedArtistName = Helper.RemoveInvalidFileNameCharacters(artistName);
                String destFileName = (i + 1).ToString() + ".jpg";
                String directoryPath = Drive + c_relativeSyncPath + "\\" + purgedArtistName;
                String sourceFilePath = directoryPath + "\\" + photos[i].DeviceFileName;
                String destFilePath = directoryPath + "\\" + destFileName;

                if (photos[i].DeviceFileName != null)
                {
                    // If the file is not marked to sync, delete it.
                    if (!photos[i].SyncPhoto)
                    {
                        try
                        {
                            File.Delete(sourceFilePath);
                        }
                        catch (DirectoryNotFoundException)
                        {
                            // If the directory isn't found, then the file clearly isn't there anyway. So let's just continue.
                            continue;
                        }
                        finally
                        {
                            photos[i].DeviceFileName = null;
                        }
                    }
                    // If the photo has a device file name (ie. already on device) and the old device file name doesn't 
                    // match the new file name (ie. it needs to be moved), move (rename) it.
                    else if (photos[i].DeviceFileName.CompareTo(destFileName) != 0)
                    {
                        // If there is no file at the new file path, go ahead and move it.
                        if (!File.Exists(destFilePath))
                        {
                            File.Move(sourceFilePath, destFilePath);
                            photos[i].DeviceFileName = destFileName;
                        }
                        // If a file already exists at the new file path, rename the old file first and replace it with the new file.
                        else
                        {
                            for (int j = i + 1; j < photos.Count; j++)
                            {
                                if (destFileName.CompareTo(photos[j].DeviceFileName) == 0)
                                {
                                    String markedFileName = (i + 1).ToString() + c_oldFileMarker + ".jpg";

                                    try
                                    {
                                        File.Move(directoryPath + "\\" + photos[j].DeviceFileName, directoryPath + "\\" + markedFileName);
                                    }
                                    catch (IOException)
                                    {
                                        File.Delete(directoryPath + "\\" + markedFileName);
                                        File.Move(directoryPath + "\\" + photos[j].DeviceFileName, directoryPath + "\\" + markedFileName);
                                    }

                                    photos[j].DeviceFileName = markedFileName;

                                    try
                                    {
                                        File.Move(sourceFilePath, destFilePath);
                                        photos[i].DeviceFileName = destFileName;
                                    }
                                    catch (FileNotFoundException)
                                    {
                                        photos[i].DeviceFileName = null;
                                    }

                                    break;
                                }
                            }
                        }
                    }
                } // end of outer if
            } // end of for

            return;
        }

    }
}
